#include "log.h"
#include "mysql_client.h"

Mysql::Mysql(const char* name, const char* host,
		const char* user, const char* pass, unsigned int port):
		_name(name), _host(host), _user(user), _pass(pass), _port(port)
{
	mysql_ptr = NULL;
	connect();
}

Mysql::~Mysql()
{
	disconnect();

	/* fix mysql client memory leak bug. */
	mysql_library_end();
}

bool Mysql::connect()
{
	my_bool my_true = true;
	mysql_init(&mysql_connection);
	
	/* set mysql auto reconnect options. */
	if(mysql_options(&mysql_connection, MYSQL_OPT_RECONNECT, &my_true))
		goto error_exit;
	
	if(NULL == (mysql_ptr = mysql_real_connect(&mysql_connection, _host, _user, _pass, _name, _port, NULL, 0)))
		goto error_exit;
	
	return true;
	
error_exit:
	logger(PRIORITY_ERROR, "mysql connection error: %s ", mysql_error(&mysql_connection));
	return false;
}

void Mysql::disconnect()
{
	if(mysql_ptr)
		mysql_close(mysql_ptr);

	mysql_ptr = NULL;
}

bool Mysql::__real_query(const char* sql, const size_t len)
{
	if(!available())
	{
		logger(PRIORITY_ERROR, "error: '%s'", mysql_error(mysql_ptr));
		this->disconnect();
	
		/* the mysql connection is not available,  */
		logger(PRIORITY_ERROR, "disconnected: '%s'", mysql_error(mysql_ptr));
		if(!this->connect()) return false;
	}

	//zero if successful
	if(mysql_real_query(mysql_ptr, sql, len) != 0) {
		logger(PRIORITY_ERROR, "error: '%s'", mysql_error(mysql_ptr));
		return false;
	}

	return true;
}

bool Mysql::execute(const char* sql, const size_t len)
{
	return __real_query(sql, len);
}

bool Mysql::query(const char* sql, MYSQL_RES*& res)
{
	if(!__real_query(sql, strlen(sql)))
		return false;
	
	if(NULL == (res = mysql_store_result(mysql_ptr))) {
		logger(PRIORITY_ERROR, "query error: %s", mysql_error(mysql_ptr));
		return false;
	}
	
	return true;
}

bool Mysql::query(const char* sql, std::vector< std::map<std::string, std::string> >& result)
{
	MYSQL_RES *res = NULL;
	MYSQL_ROW row;
	MYSQL_FIELD * fields;
	int colnum;

	if(!this->query(sql, res))
		return false;

	colnum = mysql_num_fields(res);
	while((row = mysql_fetch_row(res)) > 0) {
		std::map<std::string, std::string> item;
		for (int i=0; i < colnum; ++i) {
			fields = mysql_fetch_field_direct(res, i);
			item[fields->name] = row[i];
		}
		result.push_back(item);
	}

	mysql_free_result(res);
	return true;
}

